package com.atguigu.gmall.activity.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.activity.mapper.SecKillMapper;
import com.atguigu.gmall.activity.mapper.SecKillOrderMapper;
import com.atguigu.gmall.activity.service.SecKillService;
import com.atguigu.gmall.common.config.RabbitService;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.SeckillOrder;
import com.atguigu.gmall.model.activity.UserRecode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 秒杀service实现类
 */
@Service
public class SecKillServiceImpl implements SecKillService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RabbitService rabbitService;

    @Autowired
    SecKillMapper secKillMapper;

    @Autowired
    SecKillOrderMapper secKillOrderMapper;

    /**
     * 获取当前时间段的秒杀商品列表
     *
     * @param date
     * @return
     */
    @Override
    public List<SeckillGoods> getGoodsList(String date) {
        List list = redisTemplate.boundHashOps("secKill" + date).values();
        return list;
    }

    /**
     * 获取商品详情
     *
     * @param date
     * @param id
     * @return
     */
    @Override
    public SeckillGoods getGoods(String date, String id) {
        SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps("secKill" + date).get(id);
        return goods;
    }

    /**
     * 用户下单排队
     *
     * @param time
     * @param userId
     * @param skuId
     * @return
     */
    public UserRecode userRecode(String time, String userId, String skuId) {
        //初始化userRecode对象
        UserRecode userRecode = new UserRecode();
        //防止用户重复下单排队
        Long increment = redisTemplate.boundValueOps("SeckillUserQueue_" + userId).increment(1);
        if (increment > 1) {
            userRecode.setStatus(3);
            userRecode.setMsg("重复排队");
            equals(userRecode);
        }
        //补充userRecode对象参数
        userRecode.setUsername(userId);
        userRecode.setCreateTime(new Date());
        userRecode.setStatus(1);
        userRecode.setGoodsId(skuId);
        userRecode.setTime(time);
        userRecode.setNum(1);
        //将用户排队信息存入redis
        redisTemplate.boundValueOps("SeckillStatus_" + userId).set(userRecode);
        //发送消息下单
        rabbitService.sendMessage("seckill_exchange", "seckill.order.add", JSONObject.toJSON(userRecode));
        //返回排队消息
        return userRecode;
    }

    /**
     * 查询用户排队信息
     *
     * @param userId
     * @return
     */
    public UserRecode getUserRecode(String userId) {
        UserRecode userRecode = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + userId).get();
        return userRecode;
    }

    /**
     * 查询秒杀订单
     *
     * @param userId
     * @param orderId
     * @return
     */
    public List<SeckillOrder> getSeKillOrderList(String userId, String orderId) {
        List<SeckillOrder> list = new ArrayList<>();
        if (orderId == null) {
            //订单号为空，查询所有秒杀订单
            list = redisTemplate.boundHashOps("SeckillOrder_" + userId).values();
        } else {
            //订单号不为空，查询单个订单
            SeckillOrder secKillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + userId).get(orderId);
            list.add(secKillOrder);
        }
        //返回秒杀订单
        return list;
    }

    /**
     * 支付成功修改订单状态
     *
     * @param map
     */
    @Override
    public void paySuccess(Map<String, String> map) throws UnsupportedEncodingException {
        //获取附加参数判断是支付宝还是微信支付
        String attach = map.get("attach");
        if (attach.isEmpty()) {
            //为空则为支付宝支付，获取支付宝附加参数信息并解码
            attach = map.get("passback_params");
            attach = URLDecoder.decode(attach, "utf-8");
        }
        //获取用户id
        Map<String, String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        //获取订单号
        String out_trade_no = map.get("out_trade_no");
        //从redis中获取订单信息
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + username).get(out_trade_no);
        //判断前置状态
        if (seckillOrder != null && seckillOrder.getStatus().equals("0")) {
            //修改订单支付状态
            seckillOrder.setStatus("1");
            //补全订单信息
            seckillOrder.setCreateTime(new Date());
            //获取订单支付订单号
            String transactionId = map.get("transaction_id");
            if (StringUtils.isEmpty(transactionId)) {
                transactionId = map.get("trade_no");
            }
            seckillOrder.setOutTradeNo(transactionId);
            //修改redis中订单状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(out_trade_no,seckillOrder);
            //将订单信息存入数据库
            secKillOrderMapper.insert(seckillOrder);
            //删除排队标识和排队状态
            redisTemplate.delete("SeckillUserQueue_" + username);
            redisTemplate.delete("SeckillStatus_" + username);
        }
    }

    /**
     * 支付失败修改订单状态
     *
     * @param map
     */
    @Override
    public void payFail(Map<String, String> map) throws UnsupportedEncodingException {
        //获取附加参数判断是支付宝还是微信支付
        String attach = map.get("attach");
        if (attach.isEmpty()) {
            //为空则为支付宝支付，获取支付宝附加参数信息并解码
            attach = map.get("passback_params");
            attach = URLDecoder.decode(attach, "utf-8");
        }
        //获取用户id
        Map<String, String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        //获取订单号
        String out_trade_no = map.get("out_trade_no");
        //从redis中获取订单信息
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + username).get(out_trade_no);
        //判断前置状态
        if (seckillOrder != null && seckillOrder.getStatus().equals("0")) {
            //修改订单支付状态
            seckillOrder.setStatus("2");
            //修改redis中订单状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(out_trade_no,seckillOrder);
            //将订单信息存入数据库
            secKillOrderMapper.insert(seckillOrder);
            //回滚库存信息,redis中还有库存则回滚redis，否则回滚数据库
            UserRecode userRecode = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + seckillOrder.getUserId()).get();
            rollBack(userRecode.getGoodsId(),userRecode.getTime(),userRecode.getNum());
            //删除排队标识和排队状态
            redisTemplate.delete("SeckillUserQueue_" + username);
            redisTemplate.delete("SeckillStatus_" + username);
        }
    }

    /**
     * 回滚库存信息,redis中还有库存则回滚redis，否则回滚数据库
     *
     * @param goodsId
     * @param time
     * @param num
     */
    private void rollBack(String goodsId, String time, Integer num) {
        //查询redis中库存信息
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(goodsId);
        if (seckillGoods == null) {
            //商品售完，回滚数据库库存
            secKillMapper.updateSecKillGoodStock(goodsId, num);
        }
        //商品未售完，回滚redis库存
        String[] goodsQueue = getSeckillGoodsQueue(goodsId, num);
        redisTemplate.boundListOps("seckillGoodsQueue_" + goodsId).leftPushAll(goodsQueue);
        redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(goodsId, num);
    }

    /**
     * 构建商品库存个数长度的数组
     *
     * @param goodsId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String goodsId, Integer stockCount) {
        //构建一个库存长度的数组
        String[] ids = new String[stockCount];
        //元素填充
        for (int i = 0; i < stockCount; i++) {
            ids[i] = goodsId;
        }
        //返回数据
        return ids;
    }
}
